<?php
/**
 * 任务
 */

namespace App\Repositories\Task;

use App\Enums\ActionEnum;
use App\Enums\RewardEnum;
use App\Enums\RoomEnum;
use App\Enums\TaskEnum;
use App\Exceptions\BasicException;
use App\Services\Tools\CurlService;
use App\Services\Tools\RedisService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class TaskRepository
{

    // 获取任务模块数据
    public function getModule($moduleId)
    {
        $redisKey = sprintf(TaskEnum::TASK_MODULE, $moduleId);
        $redisRes = Redis::get($redisKey);
        if (!$redisRes) {
            $dbRes = app("model_task_module")->where("id", $moduleId)->first();
            if (!$dbRes) {
                throw new BasicException(15001);
            }

            $data = $dbRes->toArray();
            if (!empty($data['extra_json'])) {
                $extraConfig = json_decode($data['extra_json'], 1);
                if (json_last_error()) {
                    throw new BasicException(15002);
                }
                $data['extra_config'] = $extraConfig;
                unset($data['extra_json']);
            }

            Redis::setex($redisKey, TaskEnum::TASK_MODULE_EXPIRE_TIME, json_encode($data));
        } else {
            $data = json_decode($redisRes, 1);
        }

        return $data;
    }

    // 任务模块是否处于激活状态
    public function isModuleActive($moduleId)
    {
        $module = $this->getModule($moduleId);

        return $module['status'] == 1;
    }

    // 获取模块任务配置
    public function getAllTaskConfig($moduleId)
    {
        $redisKey = sprintf(TaskEnum::TASK_CONFIG, $moduleId);
        $redisRes = Redis::get($redisKey);
        if (!$redisRes) {
            $dbRes = app("model_task_config")->where("module_id", $moduleId)->get();
            if (empty($dbRes)) {
                return [];
            }

            $config = $dbRes->toArray();

            Redis::setex($redisKey, TaskEnum::TASK_CONFIG_EXPIRE_TIME, json_encode($config));
        } else {
            $config = json_decode($redisRes, 1);
        }

        return $config;
    }

    // 根据type获取未完成的用户任务
    public function getUnFinishTaskByType($typeId, $userId)
    {
        $userTaskList = app("model_task_user")->where([
            ["is_deleted", "=", 0],
            ["status", "=", TaskEnum::TASK_USER_UN_FINISH],
            ["user_id", "=", $userId],
            ["type_id", "=", $typeId],
            ["expire_time", ">=", time()]
        ])->get();

        return $userTaskList;
    }

    // 根据type获取未未领取的用户任务
    public function getUnGetTaskByType($typeId, $userId)
    {
        $userTaskList = app("model_task_user")->where([
            ["is_deleted", "=", 0],
            ["status", "<>", TaskEnum::TASK_USER_HAS_GET],
            ["user_id", "=", $userId],
            ["type_id", "=", $typeId],
            ["expire_time", ">=", time()]
        ])->get();

        return $userTaskList;
    }

    // 获得用户的任务列表
    public function getUserTaskList($userId, $moduleId)
    {
        $whereArr = [
            ["t1.is_deleted", 0],
            ["t1.user_id", $userId],
            ["t1.module_id", $moduleId],
            ["t1.expire_time", ">=", time()]
        ];

        $taskUserModel   = app('model_task_user');
        $taskTypeModel   = app('model_task_type');
        $rewardModel     = app('model_reward');
        $rewardItemModel = app('model_reward_item');

        $result = app('model_task_user')
            ->from($taskUserModel->getTable() . " as t1")
            ->select([
                "t1.*",
                DB::raw("t2.name as task_type_name"),
                DB::raw("t3.name as reward_bag_name"),
                DB::raw("t4.name as reward_item_name"),
                DB::raw("t3.picture as reward_bag_picture"),
                DB::raw("t4.picture as reward_item_picture"),
                DB::raw("t4.type as reward_item_type"),
            ])
            ->leftJoin(DB::raw($taskTypeModel->getTable() . " as t2"), "t1.type_id", "=", "t2.id")
            ->leftJoin(DB::raw($rewardModel->getTable() . " as t3"), "t1.reward_id", "=", "t3.id")
            ->leftJoin(DB::raw($rewardItemModel->getTable() . " as t4"), "t1.reward_id", "=", "t4.id")
            ->where($whereArr)->orderBy('t1.id', 'desc')->get();

        if (count($result) == 0) {
            return [];
        }

        foreach ($result as $item) {
            if ($item->reward_type == RewardEnum::REWARD_BIG_TYPE_ITEM) {
                $item->reward_picture = empty($item->reward_item_picture) ? "" : $item->reward_item_picture;
                $item->reward_name    = empty($item->reward_item_name) ? "未知道具奖品" : $item->reward_item_name;
            } else {
                $item->reward_picture = empty($item->reward_bag_picture) ? "" : $item->reward_bag_picture;
                $item->reward_name    = empty($item->reward_bag_name) ? "未知礼包奖品" : $item->reward_bag_name;
            }
        }

        return $result;
    }

    // 获得任务列表
    public function getUserTaskListByIds($taskIds, $userId, $status)
    {
        $allUserTask = app("model_task_user")
            ->where([
                ["is_deleted", 0],
                ["user_id", $userId],
                ["status", $status],
                ["expire_time", ">=", time()]
            ])
            ->whereIn("id", $taskIds)
            ->with("reward")
            ->with("reward_detail")
            ->with("task_type")
            ->get();

        if (empty($allUserTask)) {
            return [];
        }

        return $allUserTask;
    }

    // 格式化奖品列表
    public function formatRewardList($originRewardItemList)
    {
        $result = [];
        foreach ($originRewardItemList as $item) {
            $type = RewardEnum::TASK_REWARD_MAP[$item['type']] ?? 0;

            $result[] = [
                "name"    => $item['name'],
                "picture" => $item['picture'],
                "count"   => $item['number'],
                "type"    => $type
            ];
        }

        return $result;
    }

    // 根据任务数据获取其跳转数据
    public function getLinkDataFromTask($taskData, $randomHolderId, $userRoom)
    {
        $linkOriginType = $taskData->task_type->link_type ?? 0;

        $linkParams = [];

        if (isset($taskData->task_type->link_status) && $taskData->task_type->link_status == 1) {
            $linkType = TaskEnum::TASK_LINK_CLINT_TYPE_MAP[$linkOriginType] ?? 0;

            if ($linkOriginType == TaskEnum::TASK_LINK_ANY_ROOM) {
                $linkParams['room_id'] = $randomHolderId;
            } elseif ($linkOriginType == TaskEnum::TASK_LINK_USER_ROOM) {
                if (empty($userRoom)) {
                    $linkType = TaskEnum::TASK_LINK_CLINT_TYPE_MAP[TaskEnum::TASK_LINK_USER_HOME];
                } else {
                    $linkParams['room_id'] = $userRoom->id;
                }
            }
        } else {
            $linkType = 0;
        }
        if (!empty($linkParams)) {
            $linkParams['room_type'] = 0;
            if (!empty($linkParams['room_id'])) {
                $sysTypeId                 = RedisService::getRoomDetailByRoomId($randomHolderId, 'sys_type_id');
                $linkParams['sys_type_id'] = $sysTypeId;
                $linkParams['room_type']   = RoomEnum::clientRoomType($sysTypeId);
            }
        }
        return [
            "link_type"  => $linkType,
            "link_param" => empty($linkParams) ? new \stdClass() : $linkParams,
        ];
    }

    // 根据任务数据获取其奖品数据
    public function getRewardDataFromTask($taskData)
    {
        if ($taskData->reward_type == RewardEnum::REWARD_BIG_TYPE_ITEM) {
            $type = RewardEnum::TASK_REWARD_MAP[$taskData->reward_item_type] ?? 0;
        } else {
            $type = RewardEnum::TASK_REWARD_TYPE_GIFT;
        }

        return [
            "name"    => $taskData->reward_name,
            "picture" => $taskData->reward_picture,
            "count"   => $taskData->reward_number,
            "type"    => $type
        ];
    }

    // 获取用户积分余额
    public function getScoreBalance($userId)
    {
        $scoreRes = app("model_user_score")->where([
            ["user_id", $userId]
        ])->first();

        return $scoreRes['balance'] ?? 0;
    }

    // 批量领取任务奖励
    public function batchReceiveTaskReward($userTaskList, $userId)
    {
        $taskIds = [];
        $result  = [];
        DB::connection("mysql")->transaction(function () use ($userTaskList, &$taskIds, $userId, &$result) {
            $rewardParams = [];
            foreach ($userTaskList as $userTask) {
                $rewardParams[] = [
                    "id"     => $userTask->reward_id,
                    "type"   => $userTask->reward_type,
                    "number" => $userTask->reward_number,
                ];

                $taskIds[] = $userTask->id;
            }

            app("repo_reward")->setChannel(RewardEnum::REWARD_SOURCE_TYPE_TASK);
            // 赠送奖品
            app("repo_reward")->sendRewardAll($userId, $rewardParams);

            // 改变任务状态
            $affectRows = app('model_task_user')
                ->whereIn("id", $taskIds)
                ->update([
                    "status" => TaskEnum::TASK_USER_HAS_GET
                ]);
            if (!$affectRows) {
                throw new BasicException(15018);
            }

            $result = app("repo_reward")->getRewardDetailBatch($rewardParams);
        }, 5);

        return $result;
    }

    // 获取某个任务的所有子任务数量
    public function getAllChildTaskNumber($parentUniqueId, $status)
    {
        $dbRes = app("model_task_user")
            ->where([
                ["parent_unique_id", $parentUniqueId],
                ["is_deleted", "=", 0],
                ["status", "=", $status],
            ])->count();

        return intval($dbRes);
    }

}
